home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-04-18 | 19.4 KB | 861 lines | [TEXT/MMCC] |
- //---------------------------------------------------------------------
- //---------------------------------------------------------------------
- //
- // Horrible Rickety Shell, by Dave Johnson
- //
- // © Copyright 1985 - 1995 Anyone Who Wants It,
- // All Rights Energetically Hurled as far away from me as possible.
- // Use at your own (considerable) risk.
-
-
- #include "PaperJuggling.h"
-
- extern Boolean gDoneFlag;
- extern Rect gDeskRect;
- extern MenuHandle gShellMenuHandles[];
- extern unsigned long gClickTime, gSleepTime;
- extern short gDocTitleHeight, gDocFrameWidth; // Window Stats, for use in positioning
- extern ControlActionUPP gScrollActionUPP;
-
- /*-------------------------------------------------------------------------
- DoEvent() Standard Event Handler...
- -------------------------------------------------------------------------*/
-
- void DoEvent(EventRecord *Event)
- {
- GrafPtr oldport;
-
- // Allow app to handle raw event
- if(AppDoEvent(Event) == true)
- return;
-
- // Do standard event processing
- switch(Event->what)
- {
- case activateEvt:
- DoActivate((WindowPtr)Event->message, Event->modifiers & activeFlag);
- break;
-
- case updateEvt:
- {
- WindowPtr wind = (WindowPtr)Event->message;
-
- if(IsAppWindow(wind))
- {
- GetPort(&oldport);
- SetPort(wind);
- ClipRect(&wind->portRect);
- BeginUpdate(wind);
-
- /* Draw the growbox and controls */
- UpdateControls(wind, wind->visRgn);
- DrawGrowIcon(wind);
-
- // Call the app to draw content
- AppUpdate(wind);
-
- EndUpdate(wind);
- SetPort(oldport);
- }
- }
- break;
-
- case mouseDown:
- DoMouse(Event);
- gClickTime = Event->when;
- break;
-
- case keyDown:
- case autoKey:
- DoKey(Event);
- break;
-
- case osEvt:
- DoOS(Event);
- break;
-
- case kHighLevelEvent:
- DoHighLevel(Event);
- break;
-
- case nullEvent:
- AppIdle(Event);
- break;
- }
- }
-
- void DoActivate(WindowPtr wind, Boolean activate)
- {
- DocHandle doc;
-
- if(!IsAppWindow(wind) || (doc = GetWindowDoc(wind)) == nil)
- return;
-
- SetPort(wind);
- if(activate) // an activate event
- {
-
- // the growbox and controls must be redrawn on activation.
- DrawGrowIcon(wind);
- ShowControl((*doc)->hScroll);
- ShowControl((*doc)->vScroll);
- }
- else // a deactivate event
- {
- // the growbox and controls must be redrawn on de-activation, too.
- HideControl((*doc)->hScroll);
- HideControl((*doc)->vScroll);
- DrawGrowIcon(wind);
- }
-
- // Notify app
- AppActivate(wind, activate);
- }
-
- /*------------------------------------------------------------------------
- DoMouse() Handles mousedown events...
- -------------------------------------------------------------------------*/
-
- void DoMouse(EventRecord *eventptr)
- {
- WindowPtr whichWindptr;
- Point thePt;
- long mstuff;
- short part;
- Boolean doubleClick = false;
-
-
- if((eventptr->when - gClickTime) <= GetDblTime())
- {
- doubleClick = true;
- }
- thePt = eventptr->where;
- part = FindWindow(thePt, &whichWindptr);
- switch(part)
- {
- case inDesk:
- break;
-
- case inMenuBar:
- DoAdjustMenus();
- mstuff = MenuSelect(thePt);
- DoMenus(mstuff);
- break;
-
- case inSysWindow:
- SystemClick(eventptr, whichWindptr);
- break;
-
- case inContent:
- if(whichWindptr != FrontWindow())
- SelectWindow(whichWindptr);
- else
- {
- SetPort(whichWindptr);
- GlobalToLocal(&thePt);
- DoContentClick(thePt, whichWindptr, doubleClick, eventptr);
- }
- break;
-
- case inDrag:
- DragWindow(whichWindptr, thePt, &gDeskRect);
- break;
-
- case inGrow:
- DoGrowWindow(whichWindptr, thePt);
- break;
-
- case inGoAway:
- if(TrackGoAway(whichWindptr, thePt))
- {
- DoClose(whichWindptr);
- DoAdjustMenus();
- }
- break;
-
- case inZoomIn:
- case inZoomOut:
- if(TrackBox(whichWindptr, thePt, part))
- DoZoomWindow(whichWindptr, part);
- break;
- }
- }
-
- void DoAdjustMenus(void)
- {
- MenuHandle mhndl;
- long pictSize, ignored;
- Boolean windowsUp;
-
- /* OK, first the file menu. If the windows are up, then enable Close, Save (if
- the window needs saving), and Save As. Also enable Page Setup, Print, and
- Print One. If there are no windows open, disable same. New,
- and Quit are always enabled. */
-
- windowsUp = (FrontWindow() != nil && IsAppWindow(FrontWindow()));
- mhndl = gShellMenuHandles[kFileMenu];
-
- if(windowsUp)
- {
- DocHandle doc;
-
- EnableItem(mhndl, iClose);
- doc = GetWindowDoc(FrontWindow());
- if((*doc)->dirty)
- EnableItem(mhndl, iSave);
- else
- DisableItem(mhndl, iSave);
- EnableItem(mhndl, iSaveAs);
- EnableItem(mhndl, iPageSetup);
- EnableItem(mhndl, iPrint);
- EnableItem(mhndl, iPrintOne);
- }
- else // The windows are closed
- {
- DisableItem(mhndl, iClose);
- DisableItem(mhndl, iSave);
- DisableItem(mhndl, iSaveAs);
- DisableItem(mhndl, iPageSetup);
- DisableItem(mhndl, iPrint);
- DisableItem(mhndl, iPrintOne);
- }
-
- /* Now the Edit Menu. If the windows are up, enable Cut, Copy, and Clear
- automatically, and Undo and Paste conditionally. Otherwise, disable everything */
-
- mhndl = gShellMenuHandles[kEditMenu];
- if(windowsUp)
- {
- EnableItem(mhndl, iCut);
- EnableItem(mhndl, iCopy);
- EnableItem(mhndl, iClear);
-
- // For Paste: have to see if there is a PICT in the scrap
- pictSize = GetScrap(nil, 'PICT', &ignored);
- if(pictSize > 0) // We have a PICT in the scrap
- EnableItem(mhndl, iPaste);
- else
- DisableItem(mhndl, iPaste);
-
- // Now Undo:
- DisableItem(mhndl, iUndo);
- }
- else
- {
- DisableItem(mhndl, iUndo);
- DisableItem(mhndl, iCut);
- DisableItem(mhndl, iCopy);
- DisableItem(mhndl, iPaste);
- DisableItem(mhndl, iClear);
- }
-
- // Now the App
- AppAdjustMenus();
- }
-
-
- // Handle scrollbars
- void DoContentClick(Point thePt, WindowPtr wind, Boolean doubleClick, EventRecord *eventptr)
- {
- Point lastPoint = {0, 0};
- short part, value;
- ControlHandle control;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- // Look for a click in a scrollbar: if so deal with it
- part = FindControl(thePt, wind, &control);
- if(part != 0)
- {
- switch ( part )
- {
- // The thumb is special, and doesn't use the Action Proc
- case inThumb:
- value = GetCtlValue(control);
- part = TrackControl(control, thePt, nil);
- if ( part != 0 ) // Good thumb drag
- {
- value -= GetCtlValue(control);
- // value now has CHANGE in value; if value changed, scroll
- if ( value != 0 )
- if ( control == (*doc)->hScroll )
- DoScroll(wind, value, 0, true);
- else
- DoScroll(wind, 0, value, true);
- }
- break;
-
- default: // they clicked in an arrow, so track & scroll
- value = TrackControl(control, thePt, gScrollActionUPP);
- break;
- }
- }
- else
- AppClick(thePt, wind, doubleClick, eventptr);
- }
-
- // Grow the window, adjusting scroll bars and such, then inform the App what happened
- void DoGrowWindow(WindowPtr wind, Point where)
- {
- Rect limits;
- long size;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- // Do nothing if not our window
- if(IsAppWindow(wind) == false)
- return;
-
- // Set up size limits
- limits.top = limits.left = kMinWindowSize; // One inch minimum
- /* These are actually bigger than the maximum size of the portRect,
- since the outline dragged by GrowWindow is the outline of the window frame,
- not its portRect */
- limits.right = (*doc)->contentSize.h + kScrollAdjust + gDocFrameWidth;
- limits.bottom = (*doc)->contentSize.v + kScrollAdjust + gDocFrameWidth;
-
- // Let the user grow the window
- size = GrowWindow(wind, where, &limits);
-
- /* If the size changed, then erase the scrollbars and grow box area and size the
- window, adjusting the scroll bars and so on */
- if(size != 0)
- {
- Rect tempRect;
- short hSize, vSize;
-
- SetPort(wind);
-
- // Should erase the scrollbars and grow box area before resizing the window:
- // make a rect for the growBox
- tempRect = wind->portRect;
- tempRect.top = tempRect.bottom - kScrollAdjust;
- tempRect.left = tempRect.right - kScrollAdjust;
-
- // Erase it and the scroll bars
- EraseRect(&tempRect);
- InvalRect(&tempRect); // add to update region
- HideControl((*doc)->hScroll);
- HideControl((*doc)->vScroll);
-
- /* OK, size it, but first make sure that the size is within limits (users
- can hold down the command key to bypass the limit, but we won't let 'em).
- Note that we subtract from the limits to account for the window frame */
- hSize = LoWord(size);
- vSize = HiWord(size);
- if(hSize > limits.right - gDocFrameWidth) hSize = limits.right - gDocFrameWidth;
- if(vSize > limits.bottom - gDocFrameWidth) vSize = limits.bottom - gDocFrameWidth;
- SizeWindow(wind, hSize, vSize, true);
- ClipRect(&wind->portRect);
-
- // Reset gx clip
- ResetGXClip(wind);
-
- // adjust scrollBars
- AdjustScrollbars(wind, true);
-
- // re-show controls and grow icon if in the front
- if(FrontWindow() == wind)
- {
- ShowControl((*doc)->hScroll);
- ShowControl((*doc)->vScroll);
- DrawGrowIcon(wind);
- }
-
- // Tell application about it
- AppGrowWindow(wind, hSize, vSize);
- }
- }
-
- void DoZoomWindow(WindowPtr wind, short zoomDir)
- {
- Rect worldRect = {0, 0, 0, 0};
- DocHandle doc;
-
- // Do nothing if not our window
- doc = GetWindowDoc(wind);
- if(doc == nil)
- return;
-
- // Get the maximum size of the window, and set up the window for the zoom
- worldRect.right = (*doc)->contentSize.h; // top left is always 0, 0
- worldRect.bottom = (*doc)->contentSize.v;
- ReadyWZoom(wind, zoomDir, worldRect.right + kScrollAdjust, worldRect.bottom + kScrollAdjust);
-
- /* Ok, zoom that sucker. Erase the window completely first: cosmetically this looks
- good */
- SetPort(wind);
- EraseRect(&wind->portRect);
- ZoomWindow(wind, zoomDir, true);
- ClipRect(&wind->portRect);
-
- // Reset gx clip
- ResetGXClip(wind);
-
- // If window is in fromt, reset scroll bars, etc, hiding them first
- // to avoid unnecessary drawing.
- if(FrontWindow() == wind)
- {
- HideControl((*doc)->hScroll);
- HideControl((*doc)->vScroll);
- AdjustScrollbars(wind, true);
- ShowControl((*doc)->hScroll);
- ShowControl((*doc)->vScroll);
- DrawGrowIcon(wind);
- }
-
- // Tell the App what happened
- AppZoomWindow(wind, zoomDir);
- }
-
- /*-----------------------------------------------------------------------
- DoKey() Handles keypresses...
- ------------------------------------------------------------------------*/
-
- void DoKey(EventRecord *eventptr)
- {
- char key;
-
- key = (char)(eventptr->message);
- if(eventptr->modifiers & cmdKey)
- {
- AppAdjustMenus();
- DoMenus(MenuKey(key));
- }
- }
-
- /*-----------------------------------------------------------------------
- DoOS() Handles suspend and resume events, ignores mouse moved events
- ------------------------------------------------------------------------*/
-
- void DoOS(EventRecord *eventPtr)
- {
- // Get the high byte of the message.
- switch ((eventPtr->message >> 24) & 0x0FF)
- {
- case suspendResumeMessage:
- {
- Boolean resuming = eventPtr->message & resumeFlag;
- WindowPtr window;
-
- if(resuming) // if resume event
- { // we're switching back from another app so..
- gSleepTime = 0; // speed up
-
- // On a resume event, we need to call GXUpdateJob on all of our
- // documents' jobs. This is important because the user may have
- // just changed something which affects our jobs (like the size
- // of the paper in the printer).
- //
- // Since our application stores our document references in the refCon fields
- // of our documents' windows, we just loop through every one of our windows,
- // extract our document pointers and update the associated jobs.
-
- window = FrontWindow();
- while (window != nil)
- {
- if ( IsAppWindow(window) )
- GXUpdateJob(GetWindowGXJob(window));
- window = (WindowPtr) ((WindowPeek) window)->nextWindow;
- }
- }
- else // if suspend event
- gSleepTime=80; // we're switching to another app so slow down...
-
- // Since I set the doesActivateOnFGSwitch flag in the SIZE resource, I need to
- // activate the front window too.
- DoActivate(FrontWindow(), resuming);
- }
- break;
-
- case mouseMovedMessage:
- break;
- }
- }
-
-
- /*-----------------------------------------------------------------------
- DoHighLevel() Handles high level events (including Apple Events)
- ------------------------------------------------------------------------*/
-
- void DoHighLevel(EventRecord *eventPtr)
- {
- OSErr err;
-
- // Assume it's an Apple Event, since we don't define any others
- err = AEProcessAppleEvent(eventPtr);
- if(err != noErr)
- SysBeep(10);
- }
-
-
- /*-----------------------------------------------------------------------
- DoMenus() Handles a menu selection...
- ------------------------------------------------------------------------*/
-
- void DoMenus(long mstuff)
- {
- short id, item;
-
- if(HiWord(mstuff) == 0)
- return;
-
- id = HiWord(mstuff);
- item = LoWord(mstuff);
- switch(id)
- {
- case kAppleMenuID:
- DoApple(item);
- break;
-
- case kFileMenuID:
- DoFile(item);
- break;
-
- case kEditMenuID:
- DoEdit(item);
- break;
-
- default:
- AppMenu(id, item);
- break;
- }
- HiliteMenu(0);
- }
-
- /*-----------------------------------------------------------------------
- DoApple() Handles apple menu...
- ------------------------------------------------------------------------*/
-
- void DoApple(short item)
- {
- Str255 name;
-
- switch(item)
- {
- case iAbout:
- Alert(kAboutAlertID, nil);
- break;
-
- default:
- GetItem(gShellMenuHandles[kAppleMenu], item, name);
- OpenDeskAcc(name);
- }
- }
-
- /*-----------------------------------------------------------------------
- DoFile() Handles File menu...
- ------------------------------------------------------------------------*/
-
- void DoFile(short item)
- {
- WindowPtr wind = FrontWindow();
-
- switch(item)
- {
- case iNew: // New...
- AppNew(0, 0);
- break;
-
- case iOpen: // Open...
- AppOpen();
- break;
-
- case iClose: // Close...
- DoClose(wind);
- break;
-
- case iSave: // Save...
- AppSave(wind);
- break;
-
- case iSaveAs: // Save As...
- AppSaveAs(wind);
- break;
-
- case iPageSetup: // Page Setup...
- AppPageSetup(wind);
- break;
-
- case iPrint: // Print...
- AppPrint(wind);
- break;
-
- case iPrintOne: // Print...
- AppPrintOne(wind);
- break;
-
- case iQuit: // Quit
- // If the user cancels any saves CloseAllDocs returns false, otherwise it returns true
- gDoneFlag = CloseAllDocs();
- break;
- }
- DoAdjustMenus(); // Keep Menus up to date
- }
-
- /*-----------------------------------------------------------------------
- void DoEdit() Handles Edit menu...
- ------------------------------------------------------------------------*/
-
- void DoEdit(short item)
- {
- /* First call SystemEdit to let a DA do editing, if one is frontmost. We
- pass it the item - 1 since the constants for the edit commands are zero-based */
- if(SystemEdit(item - 1) == false)
- {
- // The command is for the app since SystemEdit didn't handle it.
- switch(item)
- {
- case iUndo:
- AppUndo();
- break;
-
- case iCut:
- AppCut();
- break;
-
- case iCopy:
- AppCopy();
- break;
-
- case iPaste:
- AppPaste();
- break;
-
- case iClear:
- AppClear();
- break;
- }
- }
- }
-
- //
- Boolean DoClose(WindowPtr wind)
- {
- Boolean closeIt = true;
- DocHandle doc;
-
- doc = GetWindowDoc(wind);
- if(doc != nil)
- {
- // If it needs saving, do the dialog
- if((*doc)->dirty)
- {
- short rslt;
-
- rslt = SaveChangesDlog();
- switch(rslt)
- {
- case 1: // Save
- closeIt = AppSave(wind); /* AppSave() returns true only if the save
- completed successfuly (user didn't cancel,
- no errors */
- break;
-
- case 4: // No save
- break; // closeIt already true.
-
- case 2: // Cancel
- closeIt = false;
- break;
- }
- }
-
- // Kill the window, if indicated
- if(closeIt)
- {
- AppClose(wind);
- }
- }
- return closeIt;
- }
-
- /* Apple Event handlers */
- pascal OSErr OAPPHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
- {
- OSErr err;
-
- err = MyGotRequiredParams(theAEvent);
- if (err)
- return err;
- else {
- // Do anything that should happen on an Open.
- CursHandle curs;
-
- // Set cursor to watch
- curs = GetCursor(watchCursor);
- SetCursor(*curs);
-
- // Make a new document
- // AppNew(0, 0);
-
- // Set cursor to arrow
- SetCursor(&qd.arrow);
-
- return noErr;
- }
- }
-
- pascal OSErr ODOCHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
- {
- FSSpec myFSS;
- AEDescList docList;
- OSErr err;
- long index, itemsInList;
- Size actualSize;
- AEKeyword keywd;
- DescType returnedType;
-
- // get the direct parameter--a descriptor list--and put
- // it into docList
- err = AEGetParamDesc(theAEvent, keyDirectObject,
- typeAEList, &docList);
- if (err)
- return err;
-
- // check for missing required parameters
- err = MyGotRequiredParams(theAEvent);
- if (err) {
- // an error occurred: do the necessary error handling
- err = AEDisposeDesc(&docList);
- return err;
- }
-
- // count the number of descriptor records in the list
- err = AECountItems (&docList, &itemsInList);
-
- // now get each descriptor record from the list, coerce
- // the returned data to an FSSpec record, and open the
- // associated file
- for (index = 1; index <= itemsInList; index++)
- {
- err = AEGetNthPtr(&docList, index, typeFSS, &keywd,
- &returnedType, (Ptr)&myFSS,
- sizeof(myFSS), &actualSize);
- if (err)
- SysBeep(10);
-
- // Open the file
- err = OpenJuggleFile(&myFSS, nil);
-
- if (err)
- SysBeep(10);
- }
-
- err = AEDisposeDesc(&docList);
- DoAdjustMenus();
- return noErr;
- }
-
- pascal OSErr PDOCHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
- {
- FSSpec myFSS;
- AEDescList docList;
- OSErr err;
- long index, itemsInList;
- Size actualSize;
- AEKeyword keywd;
- DescType returnedType;
- WindowPtr wind;
-
- // get the direct parameter--a descriptor list--and put
- // it into docList
- err = AEGetParamDesc(theAEvent, keyDirectObject,
- typeAEList, &docList);
- if (err)
- return err;
-
- // check for missing required parameters
- err = MyGotRequiredParams(theAEvent);
- if (err) {
- // an error occurred: do the necessary error handling
- err = AEDisposeDesc(&docList);
- return err;
- }
-
- // count the number of descriptor records in the list
- err = AECountItems (&docList, &itemsInList);
-
- // now get each descriptor record from the list, coerce
- // the returned data to an FSSpec record, and open the
- // associated file
- for (index = 1; index <= itemsInList; index++)
- {
- err = AEGetNthPtr(&docList, index, typeFSS, &keywd,
- &returnedType, (Ptr)&myFSS,
- sizeof(myFSS), &actualSize);
- if (err)
- SysBeep(10);
-
- // Open the file, making a new window
- err = OpenJuggleFile(&myFSS, &wind);
- if(err == noErr)
- {
- err = AppPrintOne(wind);
- DoClose(wind);
- }
-
- if (err)
- SysBeep(10);
- }
-
- err = AEDisposeDesc(&docList);
- return noErr;
- }
-
- pascal OSErr QUITHandler(AppleEvent *theAEvent, AppleEvent *reply, long refcon)
- {
- OSErr err;
-
- // check for missing required parameters
- err = MyGotRequiredParams(theAEvent);
- if (err) {
- // an error occurred: do the necessary error handling
- return err;
- }
-
- // Set the global flag if the user doesn't cancel
- gDoneFlag = CloseAllDocs();
- if(gDoneFlag == false)
- return userCanceledErr;
- else
- return noErr;
- }
-
- OSErr MyGotRequiredParams (AppleEvent *theAEvent)
- {
- DescType returnedType;
- Size actualSize;
- OSErr err;
-
- err = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
- typeWildCard, &returnedType,
- nil, 0, &actualSize);
-
- if (err == errAEDescNotFound) // you got 'em all
- return noErr;
- else
- if (err == noErr) // you missed a required parameter
- return errAEParamMissed;
- else // the call to AEGetAttributePtr failed
- return err;
- }
-
-
- /*---------------------------------
- void BailOut() Clean up and split...
- ----------------------------------- */
-
- void BailOut(void)
- {
- AppCleanUp();
- ExitToShell();
- }
-
-